/*
 * TODO: perhaps that should be renamed to SvgWriter or something
 */

package serveursvg;

import java.awt.Point;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 *
 */
public class MessageSVG
    {

    private static int ESPACE_ENTRE_LDV = 50;
    private static int MARGE = 30;
    private static int HAUTEUR_SECTION_CRITIQUE=5;

    private int dernierePositionMessage;
    private int dernierePositionLDV;
    SvgHelper svg = new SvgHelper();
    HashMap<Integer, Integer> ligneDeVie = new HashMap<Integer, Integer>();
    HashMap<Integer, Semaphore> ligneDeVieSemaphore =
            new HashMap<Integer, Semaphore>();

    MessageSVG()
    {
        clearContent();
    }

    private void releaseOrCreateLigneDeVieSemaphore(int pid)
    {
        if(!ligneDeVieSemaphore.containsKey(pid))
        {
           ligneDeVieSemaphore.put(pid, new Semaphore(0));
        }
        ligneDeVieSemaphore.get(pid).release();
    }

    private void acquireOrCreateLigneDeVieSemaphore(int pid)
    {
        if (!ligneDeVieSemaphore.containsKey(pid))
        {
            ligneDeVieSemaphore.put(pid, new Semaphore(0));
        }
        try
        {
            ligneDeVieSemaphore.get(pid).acquire();
        } catch (InterruptedException ex)
        {
            Logger.getLogger(MessageSVG.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void creerEvenementLocal(int pid, int dateDeb){
        svg.tracerTrait(new Point(dateDeb,getPIDPosition(pid)-10),
                new Point(dateDeb, getPIDPosition(pid)+10), SvgHelper.YELLOW);
        setDernierePositionMessage(dateDeb);

    }

    public void dessinerREQ(int pidInit, int pidDest, int dateDeb, int dateFin){
        svg.tracerFleche(new Point(dateDeb*20, getPIDPosition(pidInit)),
                new Point(dateFin*20, getPIDPosition(pidDest)), SvgHelper.RED);
        setDernierePositionMessage(dateFin*20);
    }

    public void dessinerREQClock(int pidInit, int pidDest, int dateDeb, int dateFin){
        svg.tracerFleche(new Point(dateDeb*20, getPIDPosition(pidInit)),
                new Point(dateFin*20, getPIDPosition(pidDest)), SvgHelper.RED);
        svg.ecrireTexte(new Point(dateDeb*20, getPIDPosition(pidInit)), "12",
                String.valueOf(dateDeb),SvgHelper.BLACK);
        svg.ecrireTexte(new Point(dateFin*20, getPIDPosition(pidDest)), "12",
                String.valueOf(dateFin), SvgHelper.BLACK);
        setDernierePositionMessage(dateFin*20);
    }

    public void dessinerREP(int pidInit, int pidDest, int dateDeb, int dateFin){
        svg.tracerFleche(new Point(dateDeb, getPIDPosition(pidInit)),
                new Point(dateFin, getPIDPosition(pidDest)), SvgHelper.BLEUE);
        setDernierePositionMessage(dateFin);
    }

    public void dessinerREAL(int pidInit, int pidDest, int dateDeb, int dateFin, String pid, String msg){
        svg.tracerFleche(new Point(dateDeb*20, getPIDPosition(pidInit)),
                new Point(dateFin*20, getPIDPosition(pidDest)), SvgHelper.GREEN);
        //horloge
        svg.ecrireTexte(new Point(dateDeb*20, getPIDPosition(pidInit)), "12",
                String.valueOf(dateDeb),SvgHelper.BLACK);
        svg.ecrireTexte(new Point(dateFin*20, getPIDPosition(pidDest)), "12",
                String.valueOf(dateFin), SvgHelper.BLACK);
        //message
        svg.ecrireTexte(new Point(dateDeb*20, getPIDPosition(pidInit)+15), "4", pid + " " +
                msg, SvgHelper.BLACK);
        setDernierePositionMessage(dateFin);
    }

    public void dessinerProcessus(int pid){
        dernierePositionLDV+=ESPACE_ENTRE_LDV;
        ligneDeVie.put(pid, dernierePositionLDV);
        releaseOrCreateLigneDeVieSemaphore(pid);
    }

    public void dessinerSC(int pidInit, int dateDeb, int dateFin){
        svg.tracerRectangle(new Point(dateDeb, getPIDPosition(pidInit)-HAUTEUR_SECTION_CRITIQUE),new Point(
                dateFin, HAUTEUR_SECTION_CRITIQUE), SvgHelper.RED);
        setDernierePositionMessage(dateFin);
    }

    public void genererSVG(String param){
        genererLigneVie();
        svg.setHeader(dernierePositionMessage+200+MARGE, dernierePositionLDV+MARGE);
        svg.writeSVGToFile(param);
    }

    private void genererLigneVie(){
        Set keySet = ligneDeVie.keySet();
        Iterator it = keySet.iterator();
        svg.setLigneDeVie("");
        String temp ="";
        while(it.hasNext()){
            Integer pos = (Integer) ligneDeVie.get((Integer)it.next());
            temp += svg.ligneDeVie(new Point(20, pos),
                    new Point(dernierePositionMessage+200,pos), SvgHelper.BLACK);
        }
        svg.setLigneDeVie(temp);
    }

    /**
     * mind not to let a process try to read from ligneDeVie for a process id
     * that wasn't yet added, this is why we added the semaphores
     * @param pid
     * @return
     */
    private int getPIDPosition(int pid)
    {
        /*
         * workaround to lock until the pid was added by
         * dessinerProcessus()
         */
        acquireOrCreateLigneDeVieSemaphore(pid);
        ligneDeVieSemaphore.get(pid).release();
        return (Integer) ligneDeVie.get(pid);
    }

    public final void clearContent()
    {
        svg.setContent("");
        dernierePositionLDV = 0;
        this.dernierePositionMessage = MARGE*2;
    }

    private void setDernierePositionMessage(int dateFin){
        if(dateFin>dernierePositionMessage){
            dernierePositionMessage=dateFin;
        }
    }
     public void ecrireTexte(Point x, String taillePolice, String texte){
         svg.ecrireTexte(new Point(x.x,x.y), taillePolice, texte, SvgHelper.BLACK);
         setDernierePositionMessage(x.x);
     }
}


